<?php

namespace api\modules\v1\forms\buss;

use api\modules\common\services\UploadService;
use common\models\base\Project;
use common\models\base\Tags;
use common\models\base\ToolCategory;
use common\models\buss\CommonRelation;
use common\models\buss\Tool;
use common\models\buss\ToolFile;
use common\models\sys\SysFile;
use services\base\CommonRelationService;
use services\base\TagsService;
use services\base\ToolCategoryService;
use services\buss\ToolFileService;
use services\member\MemberService;
use services\sys\SysFileService;
use Yii;
use yii\base\Model;


class ToolForm extends Model
{
    /**
     * @var int $id ID
     * @var int $project_id 项目ID
     * @var string $name 素材库名称
     * @var string $desc 简介说明
     * @var array $tags 标签[{value: 1, label: '标签'},{value: 0, label: '新增标签'}]
     * @var string $file 文件名
     * @var array $image 预览图
     * @var array $video 预览图
     * @var int $age_id 年龄ID
     * @var array $category_ids 分类IDs
     * @var array $file_ids 文件IDs
     * @var string $download_type 下载类型【附件：attachment、其他：other】
     */
    public $id;
    public $project_id;
    public $name;
    public $desc;
    public $tags;
    public $file;
    public $image;
    public $video;
    public $age_id;
    public $category_ids;
    public $file_ids;
    public $download_type;

    /**
     * @var Tool $_tool
     * @var Project $_project
     * @var int[] $_tagIds
     * @var Tags[] $_tagList
     * @var Tags[] $_oldTagList
     * @var int[] $_addTagIds
     * @var int[] $_delTagIds
     * @var SysFile $_file
     * @var ToolFile[] $_oldToolImageList
     * @var string[] $_addImage
     * @var string[] $_delImage
     * @var ToolFile[] $_oldToolVideoList
     * @var string[] $_addVideo
     * @var string[] $_delVideo
     * @var ToolCategory $_ageCategroy
     * @var ToolCategory[] $_categoryList
     * @var ToolCategory[] $_oldCategroyList
     * @var ToolFile[] $_downloadToolFileList
     */
    protected $_tool;
    protected $_project;
    protected $_tagIds;// 表单提交标签IDs【包含value=0,新增的】
    protected $_tagList;
    protected $_oldTagList;
    protected $_addTagIds;// 新增标签IDs
    protected $_delTagIds;// 删除标签IDs
    protected $_file;
    protected $_oldToolImageList;
    protected $_addImage;// 新增预览图
    protected $_delImage;// 删除预览图
    protected $_oldToolVideoList;
    protected $_addVideo;// 新增视频
    protected $_delVideo;// 删除视频
    protected $_ageCategroy;// 年龄
    protected $_categoryList;
    protected $_oldCategroyList;
    protected $_addCategoryIds;// 新增分类IDs
    protected $_delCategoryIds;// 删除分类IDs
    protected $_downloadToolFileList;// 下载文件
    protected $_haveProjectList;// 权限下项目列表


    public function rules()
    {
        return [
            // 参数验证
            [['project_id', 'name'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['id', 'project_id', 'name'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],
            [['id', 'download_type'], 'required', 'message' => '{attribute}不能为空', 'on' => ['download']],

            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['edit', 'delete', 'download']],
            [['project_id'], 'checkProjectId', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['name'], 'checkName', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['desc'], 'checkDesc', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['tags'], 'checkTags', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['file'], 'checkFile', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['image'], 'checkImage', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['video'], 'checkVideo', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['age_id'], 'checkAgeId', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['category_ids'], 'checkCategoryIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['file_ids'], 'checkFileIds', 'skipOnEmpty' => false, 'on' => ['download']],
            [['download_type'], 'checkDownloadType', 'skipOnEmpty' => false, 'on' => ['download']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = ['project_id', 'name', 'desc', 'tags', 'file', 'image', 'video', 'age_id', 'category_ids'];
        // 编辑
        $scenarios['edit'] = ['id', 'project_id', 'name', 'desc', 'tags', 'file', 'image', 'video', 'age_id', 'category_ids'];
        // 删除
        $scenarios['delete'] = ['id'];
        // 下载
        $scenarios['download'] = ['id', 'file_ids', 'download_type'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => '素材库名称',
            'desc' => '简介',
            'tag_ids' => '标签',
            'file' => '上传附件',
            'image' => '图片',
            'video' => '视频',
            'age_id' => '年龄',
            'category_ids' => '分类',
            'file_ids' => '文件',
        ];
    }
    /**
     * 检验素材库ID
     * @param $attribute
     * @return void
     */
    public function checkId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $tool = $this->getTool();
        if (!$tool) {
            $this->addError($attribute, '素材库不存在');
            return;
        }

        if ($tool->status == Tool::STATUS_DELETE) {
            $this->addError($attribute, '素材库已删除');
            return;
        }
    }

    /**
     * 检验素材库ID
     * @param $attribute
     * @return void
     */
    public function checkProjectId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $project = $this->getProject();
        if (empty($project)) {
            $this->addError($attribute, '项目不存在');
            return;
        }
        if ($project->status == Project::STATUS_DELETE) {
            $this->addError($attribute, '项目已删除');
            return;
        }
        if ($this->getScenario() == 'edit') {
            $tool = $this->getTool();
            if ($this->project_id == $tool->project_id) {// 未修改项目则不检验
                return;
            }
        }
        if (in_array($this->project_id, array_column($this->getHaveProjectList(), 'value')) === false) {
            $this->addError($attribute, '无权限选择当前项目');
            return;
        }
    }

    /**
     * 校验素材库名称
     * @param $attribute
     * @return void
     */
    public function checkName($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $len = mb_strlen($this->name);
        if ($len > 20) {
            $this->addError($attribute, '素材库名称过长，最多20个字');
            return;
        }

        // 是否检验
        if ($this->getScenario() == 'edit') {
            $tool = $this->getTool();
            // 素材库参数未改变【跳过】
            if ($tool->name == $this->name) {
                return;
            }
        }

        $one = Tool::findOne([
            'name' => $this->name,
            'status' => [Tool::STATUS_INVALID, Tool::STATUS_ENABLE],
        ]);
        if ($one) {
            $this->addError($attribute, "素材库【{$this->name}】已存在");
            return;
        }
    }

    /**
     * 校验网址
     * @param $attribute
     * @return void
     */
    /*public function checkUrl($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        $len = mb_strlen($this->url);
        if ($len > 256) {
            $this->addError($attribute, '网址过长，最多256个字');
            return;
        }
    }*/

    /**
     * 校验简介
     * @param $attribute
     * @return void
     */
    public function checkDesc($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        $len = mb_strlen($this->desc);
        if ($len > 256) {
            $this->addError($attribute, '简介过长，最多256个字');
            return;
        }
    }

    /**
     * 校验标签
     * @param $attribute
     * @return void
     */
    public function checkTags($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        try {
            $tagList = $this->getTagList();
        } catch (\Exception $e) {
            $this->addError($attribute, $e->getMessage());
            return;
        }
        $oldTagList = $this->getOldTagList();
        $newIds = array_column($tagList, 'id');
        $oldIds = array_column($oldTagList, 'id');
        // 新增标签
        $this->_addTagIds = array_diff($newIds, $oldIds);
        // 删除标签
        $this->_delTagIds = array_diff($oldIds, $newIds);
    }

    /**
     * 校验文件
     * @param $attribute
     * @return void
     */
    public function checkFile($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->file)) {
            return;
        }
        $file = $this->getFile();
        if (empty($file)) {
            $this->addError($attribute, '文件不存在');
            return;
        }
    }

    /**
     * 校验图片
     * @param $attribute
     * @return void
     */
    public function checkImage($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        $this->image = array_values(array_unique($this->image ?: []));

        if (count($this->image) > 10) {
            $this->addError($attribute, '图片最多上传10张');
            return;
        }
        // 检验文件格式
        $errorFile = [];
        $checkTypeArr = UploadService::$imageTypeArr;
        foreach ($this->image as $row) {
            if (in_array(substr($row, strripos($row,'.')), $checkTypeArr) == false) {
                $errorFile[] = $row;
            }
        }
        if ($errorFile) {
            $errorFiles = implode(',', $errorFile);
            $this->addError($attribute, "【{$errorFiles}】文件格式错误");
            return;
        }

        $oldImage = array_column($this->getOldToolImageList(), 'file');
        $this->_addImage = array_diff($this->image, $oldImage);
        $this->_delImage = array_diff($oldImage, $this->image);
    }

    /**
     * 校验视频
     * @param $attribute
     * @return void
     */
    public function checkVideo($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        $this->video = array_values(array_unique($this->video ?: []));

        if (count($this->video) > 5) {
            $this->addError($attribute, '视频最多上传5张');
            return;
        }
        // 检验文件格式
        $errorFile = [];
        $checkTypeArr = UploadService::$videoTypeArr;
        foreach ($this->video as $row) {
            if (in_array(substr($row, strripos($row,'.')), $checkTypeArr) == false) {
                $errorFile[] = $row;
            }
        }
        if ($errorFile) {
            $errorFiles = implode(',', $errorFile);
            $this->addError($attribute, "【{$errorFiles}】文件格式错误");
            return;
        }

        $oldVideo = array_column($this->getOldToolVideoList(), 'file');
        $this->_addVideo = array_diff($this->video, $oldVideo);
        $this->_delVideo = array_diff($oldVideo, $this->video);
    }

    /**
     * 校验年龄
     * @param $attribute
     * @return void
     */
    public function checkAgeId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->age_id)) {
            return;
        }
        $category = $this->getAgeCategory();
        if ($category->pid != ToolCategory::ID_AGE) {
            $this->addError($attribute, "非年龄分类");
            return;
        }
        if ($this->getScenario() == 'edit') {
            $tool = $this->getTool();
            if ($tool->age_id == $this->id) {
                return;
            }
        }
        if ($category->status != ToolCategory::STATUS_ENABLE) {
            $this->addError($attribute, "年龄状态异常");
            return;
        }
    }

    /**
     * 校验分类
     * @param $attribute
     * @return void
     */
    public function checkCategoryIds($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->category_ids)) {
            $this->category_ids = [];
            return;
        }

        $categoryList = $this->getCategoryList();
        foreach ($categoryList as $category) {
            if ($category->pid == 0 || $category->pid == ToolCategory::ID_AGE) {
                $this->addError($attribute, '分类错误，不能为一级分类或年龄分类');
                return;
            }
        }
        $oldCategoryList = $this->getOldCategoryList();
        $newIds = array_column($categoryList, 'id');
        $oldIds = array_column($oldCategoryList, 'id');
        // 新增分类
        $this->_addCategoryIds = array_diff($newIds, $oldIds);
        // 删除分类
        $this->_delCategoryIds = array_diff($oldIds, $newIds);

        $error = ToolCategory::find()
            ->where(['id' => $this->_addCategoryIds, 'status' => [ToolCategory::STATUS_INVALID, ToolCategory::STATUS_DELETE]])
            ->one();
        if ($error) {
            $this->addError($attribute, '新增分类异常');
            return;
        }
    }

    /**
     * 校验下载文件
     * @param $attribute
     * @return void
     */
    public function checkFileIds($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->download_type == 'attachment') {
            return;
        }
        $downloadToolFileList = $this->getDownloadToolFileList();
        if (empty($downloadToolFileList)) {
            $this->addError($attribute, "请选择下载文件");
            return;
        }
        foreach ($downloadToolFileList as $toolFile) {
            if ($toolFile->tool_id != $this->id) {
                $this->addError($attribute, "下载文件非当前素材库");
                return;
            }
        }
    }

    /**
     * 校验下载类型
     * @param $attribute
     * @return void
     */
    public function checkDownloadType($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if (in_array($this->download_type, ['attachment', 'other']) === false) {
            $this->addError($attribute, '参数错误【download_type值有误】');
            return;
        }

        if ($this->download_type == 'attachment') {
            $tool = $this->getTool();
            if (empty($tool->file)) {
                $this->addError($attribute, '附件不存在');
                return;
            }
        }
    }

    /**
     * 获取素材库信息
     * @return Tool|null
     */
    public function getTool(): ?Tool
    {
        if (empty($this->_tool)) {
            $this->_tool = Tool::findOne($this->id);
        }

        return $this->_tool;
    }

    /**
     * 获取项目信息
     * @return Project|null
     */
    public function getProject(): ?Project
    {
        if (empty($this->_project)) {
            $this->_project = Project::findOne($this->project_id);
        }

        return $this->_project;
    }

    /**
     * 获取新标签列表
     * @return Tags[]
     */
    public function getTagList(): array
    {
        if (is_null($this->_tagList)) {
            $newIds = $addTagName = [];
            $this->tags = $this->tags ?: [];
            foreach ($this->tags as $row) {
                if (empty($row['value']) && in_array($row['label'], $addTagName) === false) {
                    $addTagName[] = $row['label'];
                }
                if ($row['value']) {
                    $newIds[] = $row['value'];
                }
            }
            if ($addTagName) {
                if ($invalidTags = TagsService::getInvalidListByName(Tags::TYPE_TOOL, $addTagName)) {
                    $invalidTagNames = implode(',', array_column($invalidTags, 'name'));
                    throw new \Exception("标签【{$invalidTagNames}】被禁用，无法操作");
                }

                $service = new TagsService();
                $service->createTags([
                    'name' => implode(',', $addTagName),
                    'type' => Tags::TYPE_TOOL,
                ]);
                $addIds = array_column(TagsService::getNormalListByName(Tags::TYPE_TOOL, $addTagName), 'id');
                $newIds = array_merge($newIds, $addIds);
            }
            $this->_tagIds = $newIds;
            $this->_tagList = TagsService::getNormalListByIds(CommonRelation::TYPE_TOOL_TAG, $this->_tagIds);
        }

        return $this->_tagList;
    }

    /**
     * 获取原标签列表
     * @return Tags[]
     */
    public function getOldTagList(): array
    {
        if (empty($this->_oldTagList)) {
            $this->_oldTagList = $this->getScenario() == 'edit'
                ? TagsService::getNormalListByIds(CommonRelation::TYPE_TOOL_TAG, CommonRelationService::getToolTagIds($this->id))
                : [];
        }

        return $this->_oldTagList;
    }

    /**
     * 获取新增标签IDs
     * @return int[]
     */
    public function getAddTagIds(): array
    {
        return $this->_addTagIds ?: [];
    }

    /**
     * 获取新增标签IDs
     * @return int[]
     */
    public function getDelTagIds(): array
    {
        return $this->_delTagIds ?: [];
    }

    /**
     * 获取文件
     * @return SysFile|null
     */
    public function getFile(): ?SysFile
    {
        if (empty($this->_file)) {
            $this->_file = SysFileService::getSysFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $this->file);
        }
        return $this->_file;
    }

    /**
     * 获取原图片列表
     * @return ToolFile[]
     */
    public function getOldToolImageList(): array
    {
        if (empty($this->_oldToolImageList)) {
            $this->_oldToolImageList = in_array($this->getScenario(), ['edit', 'delete'])
                ? ToolFileService::getToolFileListByToolId($this->id, ToolFile::TYPE_IMAGE)
                : [];
        }
        return $this->_oldToolImageList;
    }

    /**
     * 获取新增图片
     * @return array
     */
    public function getAddImage(): array
    {
        return $this->_addImage ?: [];
    }

    /**
     * 获取删除图片
     * @return array
     */
    public function getDelImage(): array
    {
        return $this->_delImage ?: [];
    }

    /**
     * 获取原视频列表
     * @return ToolFile[]
     */
    public function getOldToolVideoList(): array
    {
        if (empty($this->_oldToolVideoList)) {
            $this->_oldToolVideoList = in_array($this->getScenario(), ['edit', 'delete'])
                ? ToolFileService::getToolFileListByToolId($this->id, ToolFile::TYPE_VIDEO)
                : [];
        }
        return $this->_oldToolVideoList;
    }

    /**
     * 获取新增视频
     * @return array
     */
    public function getAddVideo(): array
    {
        return $this->_addVideo ?: [];
    }

    /**
     * 获取删除视频
     * @return array
     */
    public function getDelVideo(): array
    {
        return $this->_delVideo ?: [];
    }

    /**
     * 年龄
     * @return ToolCategory|null
     */
    public function getAgeCategory(): ?ToolCategory
    {
        if (empty($this->_ageCategroy)) {
            $this->_ageCategroy = ToolCategory::findOne($this->age_id);
        }
        return $this->_ageCategroy;
    }

    /**
     * 获取新分类列表
     * @return ToolCategory[]
     */
    public function getCategoryList(): array
    {
        if (is_null($this->_categoryList)) {
            $this->_categoryList = ToolCategoryService::getNormalListByIds($this->category_ids);
        }
        return $this->_categoryList;
    }

    /**
     * 获取原分类列表
     * @return ToolCategory[]
     */
    public function getOldCategoryList(): array
    {
        if (empty($this->_oldCategroyList)) {
            $this->_oldCategroyList = $this->getScenario() == 'edit'
                ? ToolCategoryService::getNormalListByIds(CommonRelationService::getToolCategoryIds($this->id))
                : [];
        }

        return $this->_oldCategroyList;
    }


    /**
     * 获取新增分类IDs
     * @return int[]
     */
    public function getAddCategoryIds(): array
    {
        return $this->_addCategoryIds ?: [];
    }

    /**
     * 获取新增分类IDs
     * @return int[]
     */
    public function getDelCategoryIds(): array
    {
        return $this->_delCategoryIds ?: [];
    }

    /**
     * 获取下载文件列表
     * @return ToolFile[]
     */
    public function getDownloadToolFileList(): array
    {
        if (is_null($this->_downloadToolFileList)) {
            $this->file_ids = is_array($this->file_ids) ? $this->file_ids : explode(',', $this->file_ids);
            $this->_downloadToolFileList = ToolFile::findAll(['id' => $this->file_ids]);
        }
        return $this->_downloadToolFileList;
    }

    /**
     * 获取账号信息
     * @return Project[]
     */
    public function getHaveProjectList(): array
    {
        if (empty($this->_haveProjectList)) {
            $this->_haveProjectList = MemberService::getProjectEditCondition();
        }

        return $this->_haveProjectList;
    }
}
